/* ORG Usurper is a random value object generator library Copyright (C) 2007 Pierre-Antoine Grégoire This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ package org.org.usurper.springframework.namespace; import java.util.ArrayList; import java.util.List; import org.org.usurper.springframework.UsurperFactoryBean; import org.org.usurper.springframework.UsurperGeneratorSetupFactoryBean; import org.org.usurper.springframework.UsurperListFactoryBean; import org.org.usurper.springframework.UsurperMapFactoryBean; import org.org.usurper.springframework.UsurperSetFactoryBean; import org.org.usurper.springframework.aop.UsurperMethodInterceptor; import org.springframework.aop.framework.ProxyFactoryBean; import org.springframework.beans.factory.BeanDefinitionStoreException; import org.springframework.beans.factory.config.BeanDefinitionHolder; import org.springframework.beans.factory.config.RuntimeBeanReference; import org.springframework.beans.factory.parsing.BeanComponentDefinition; import org.springframework.beans.factory.support.AbstractBeanDefinition; import org.springframework.beans.factory.support.BeanDefinitionBuilder; import org.springframework.beans.factory.support.ManagedMap; import org.springframework.beans.factory.support.ManagedSet; import org.springframework.beans.factory.support.RootBeanDefinition; import org.springframework.beans.factory.xml.AbstractBeanDefinitionParser; import org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser; import org.springframework.beans.factory.xml.BeanDefinitionParser; import org.springframework.beans.factory.xml.NamespaceHandlerSupport; import org.springframework.beans.factory.xml.ParserContext; import org.springframework.core.Conventions; import org.springframework.util.StringUtils; import org.springframework.util.xml.DomUtils; import org.w3c.dom.Element; /** * The Class GeneratorsNamespaceHandler defines the Spring > 2.0 Namespace handler for Usurper. * See schema: {@link http://www.org-libs.org/org-lib-usurper/schema/generators/usurper-1.0.0.xsd} */ public class GeneratorsNamespaceHandler extends NamespaceHandlerSupport { private static final String AOP_GENERATOR_TAG = "aop-generator"; private static final String MAP_GENERATOR_TAG = "map-generator"; private static final String SET_GENERATOR_TAG = "set-generator"; private static final String BEAN_GENERATOR_TAG = "bean-generator"; private static final String LIST_GENERATOR_TAG = "list-generator"; private static final String SETUP_TAG = "setup"; private static final String PROPERTY_TYPE_HANDLER_TAG = "property-type-handler"; private static final String PROPERTY_TYPE_HANDLER_REF_TAG = "property-type-handler-ref"; private static final String SPECIFIC_PROPERTY_HANDLER_TAG = "specific-property-handler"; private static final String SPECIFIC_PROPERTY_HANDLER_REF_TAG = "specific-property-handler-ref"; private static final String INTERFACE_ATTR = "interface"; private static final String CLASS_ATTR = "class"; private static final String VALUE_CLASS_ATTR = "value-class"; private static final String KEY_CLASS_ATTR = "key-class"; private static final String SETUP_REF_ATTR = "setup-ref"; private static final String COUNT_ATTR = "count"; private static final String SETUP_PARENT_SETUP = "parent-setup"; private static final String SETUP_ARRAY_HANDLER_ATTR = "array-handler"; private static final String SETUP_ARRAY_HANDLER_REF_ATTR = "array-handler-ref"; private static final String SETUP_ENUM_HANDLER_ATTR = "enum-handler"; private static final String SETUP_ENUM_HANDLER_REF_ATTR = "enum-handler-ref"; private static final String SETUP_ON_MISSING_HANDLERS_ATTR = "on-missing-handlers"; private static final String SETUP_PROPERTY_WRITING_MECHANISM_ATTR = "property-writing-mechanism"; private static final String SETUP_COUNT_CALLBACK_ATTR = "count-callback"; private static final String SETUP_COUNT_CALLBACK_REF_ATTR = "count-callback-ref"; private static final String PROPERTY_TYPE_HANDLER_PROPERTY_TYPE_ATTR = "property-type"; private static final String PROPERTY_TYPE_HANDLER_HANDLER_CLASS_ATTR = "handler-class"; private static final String PROPERTY_TYPE_HANDLER_HANDLER_REF_ATTR = "handler-ref"; private static final String SPECIFIC_PROPERTY_HANDLER_TARGET_CLASS_ATTR = "target-class"; private static final String SPECIFIC_PROPERTY_HANDLER_TARGET_PROPERTY_ATTR = "target-property"; private static final String SPECIFIC_PROPERTY_HANDLER_HANDLER_CLASS_ATTR = "handler-class"; private static final String SPECIFIC_PROPERTY_HANDLER_HANDLER_REF_ATTR = "handler-ref"; private static final String USURPER_GENERATOR_SETUP_PROP = "usurperGeneratorSetup"; private static final String USURPED_CLASS_NAME_PROP = "usurpedClassName"; private static final String USURPED_VALUE_CLASS_NAME_PROP = "usurpedValueClassName"; private static final String USURPED_KEY_CLASS_NAME_PROP = "usurpedKeyClassName"; private static final String PROXYFACTORYBEAN_INTERCEPTOR_NAMES_PROP = "interceptorNames"; private static final String PROXYFACTORYBEAN_PROXY_INTERFACES_PROP = "proxyInterfaces"; private static final String USURPER_INTERCEPTOR_BEAN_ID = "usurperInterceptor"; public void init() { registerBeanDefinitionParser(BEAN_GENERATOR_TAG, new BeanGeneratorBeanDefinitionParser()); registerBeanDefinitionParser(LIST_GENERATOR_TAG, new ListOfBeansGeneratorBeanDefinitionParser()); registerBeanDefinitionParser(SET_GENERATOR_TAG, new SetOfBeansGeneratorBeanDefinitionParser()); registerBeanDefinitionParser(MAP_GENERATOR_TAG, new MapOfBeansGeneratorBeanDefinitionParser()); registerBeanDefinitionParser(AOP_GENERATOR_TAG, new AopGeneratorBeanDefinitionParser()); registerBeanDefinitionParser(SETUP_TAG, new SetupBeanDefinitionParser()); } private static class AopGeneratorBeanDefinitionParser extends AbstractBeanDefinitionParser implements BeanDefinitionParser { @Override protected AbstractBeanDefinition parseInternal(Element element, ParserContext parserContext) { String interfaceName = element.getAttribute(INTERFACE_ATTR); String setupRef = element.getAttribute(SETUP_REF_ATTR); // Create the Interceptor definition RootBeanDefinition interceptorDefinition = new RootBeanDefinition(UsurperMethodInterceptor.class); if (StringUtils.hasText(setupRef)) { interceptorDefinition.getPropertyValues().addPropertyValue(USURPER_GENERATOR_SETUP_PROP, setupRef); } try { BeanDefinitionHolder holder = new BeanDefinitionHolder(interceptorDefinition, USURPER_INTERCEPTOR_BEAN_ID); registerBeanDefinition(holder, parserContext.getRegistry()); if (shouldFireEvents()) { BeanComponentDefinition componentDefinition = new BeanComponentDefinition(holder); postProcessComponentDefinition(componentDefinition); parserContext.registerComponent(componentDefinition); } } catch (BeanDefinitionStoreException ex) { parserContext.getReaderContext().error(ex.getMessage(), element); } List<String> interceptorNames = new ArrayList<String>(); interceptorNames.add(USURPER_INTERCEPTOR_BEAN_ID); // Create the target Class definition. RootBeanDefinition targetDefinition = new RootBeanDefinition(ProxyFactoryBean.class); targetDefinition.setSource(parserContext.extractSource(element)); targetDefinition.getPropertyValues().addPropertyValue(PROXYFACTORYBEAN_PROXY_INTERFACES_PROP, interfaceName); targetDefinition.getPropertyValues().addPropertyValue(PROXYFACTORYBEAN_INTERCEPTOR_NAMES_PROP, interceptorNames); return targetDefinition; } } private static class BeanGeneratorBeanDefinitionParser extends AbstractSingleBeanDefinitionParser implements BeanDefinitionParser { @SuppressWarnings("unchecked") @Override protected Class getBeanClass(Element element) { return UsurperFactoryBean.class; } @Override protected void doParse(Element element, BeanDefinitionBuilder bean) { String usurpedClass = element.getAttribute(CLASS_ATTR); bean.addPropertyValue(USURPED_CLASS_NAME_PROP, usurpedClass); String setupRef = element.getAttribute(SETUP_REF_ATTR); if (StringUtils.hasText(setupRef)) { bean.addPropertyReference(USURPER_GENERATOR_SETUP_PROP, setupRef); } } } private static class ListOfBeansGeneratorBeanDefinitionParser extends AbstractSingleBeanDefinitionParser implements BeanDefinitionParser { @SuppressWarnings("unchecked") @Override protected Class getBeanClass(Element element) { return UsurperListFactoryBean.class; } @Override protected void doParse(Element element, BeanDefinitionBuilder bean) { String usurpedClass = element.getAttribute(CLASS_ATTR); bean.addPropertyValue(USURPED_CLASS_NAME_PROP, usurpedClass); String setupRef = element.getAttribute(SETUP_REF_ATTR); if (StringUtils.hasText(setupRef)) { bean.addPropertyReference(USURPER_GENERATOR_SETUP_PROP, setupRef); } String count = element.getAttribute(COUNT_ATTR); if (StringUtils.hasText(count)) { bean.addPropertyValue(COUNT_ATTR, Integer.valueOf(count)); } } } private static class MapOfBeansGeneratorBeanDefinitionParser extends AbstractSingleBeanDefinitionParser implements BeanDefinitionParser { @SuppressWarnings("unchecked") @Override protected Class getBeanClass(Element element) { return UsurperMapFactoryBean.class; } @Override protected void doParse(Element element, BeanDefinitionBuilder bean) { String usurpedKeyClass = element.getAttribute(KEY_CLASS_ATTR); bean.addPropertyValue(USURPED_KEY_CLASS_NAME_PROP, usurpedKeyClass); String usurpedValueClass = element.getAttribute(VALUE_CLASS_ATTR); bean.addPropertyValue(USURPED_VALUE_CLASS_NAME_PROP, usurpedValueClass); String setupRef = element.getAttribute(SETUP_REF_ATTR); if (StringUtils.hasText(setupRef)) { bean.addPropertyReference(USURPER_GENERATOR_SETUP_PROP, setupRef); } String count = element.getAttribute(COUNT_ATTR); if (StringUtils.hasText(count)) { bean.addPropertyValue(COUNT_ATTR, Integer.valueOf(count)); } } } private static class SetOfBeansGeneratorBeanDefinitionParser extends AbstractSingleBeanDefinitionParser implements BeanDefinitionParser { @SuppressWarnings("unchecked") @Override protected Class getBeanClass(Element element) { return UsurperSetFactoryBean.class; } @Override protected void doParse(Element element, BeanDefinitionBuilder bean) { String usurpedClass = element.getAttribute(CLASS_ATTR); bean.addPropertyValue(USURPED_CLASS_NAME_PROP, usurpedClass); String setupRef = element.getAttribute(SETUP_REF_ATTR); if (StringUtils.hasText(setupRef)) { bean.addPropertyReference(USURPER_GENERATOR_SETUP_PROP, setupRef); } String count = element.getAttribute(COUNT_ATTR); if (StringUtils.hasText(count)) { bean.addPropertyValue(COUNT_ATTR, Integer.valueOf(count)); } } } private static class SetupBeanDefinitionParser extends AbstractSingleBeanDefinitionParser implements BeanDefinitionParser { @SuppressWarnings("unchecked") @Override protected Class getBeanClass(Element element) { return UsurperGeneratorSetupFactoryBean.class; } @SuppressWarnings("unchecked") @Override protected void doParse(Element element, BeanDefinitionBuilder bean) { String parentSetup = element.getAttribute(SETUP_PARENT_SETUP); if (StringUtils.hasText(parentSetup)) { bean.addPropertyReference(Conventions.attributeNameToPropertyName(SETUP_PARENT_SETUP), parentSetup); } String arrayHandler = element.getAttribute(SETUP_ARRAY_HANDLER_ATTR); String arrayHandlerRef = element.getAttribute(SETUP_ARRAY_HANDLER_REF_ATTR); if (StringUtils.hasText(arrayHandler)) { bean.addPropertyValue(Conventions.attributeNameToPropertyName(SETUP_ARRAY_HANDLER_ATTR) + "Name", arrayHandler); } else if (StringUtils.hasText(arrayHandlerRef)) { bean.addPropertyReference(Conventions.attributeNameToPropertyName(SETUP_ARRAY_HANDLER_ATTR), arrayHandlerRef); } String enumHandler = element.getAttribute(SETUP_ENUM_HANDLER_ATTR); String enumHandlerRef = element.getAttribute(SETUP_ENUM_HANDLER_REF_ATTR); if (StringUtils.hasText(enumHandler)) { bean.addPropertyValue(Conventions.attributeNameToPropertyName(SETUP_ENUM_HANDLER_ATTR + "Name"), enumHandler); } else if (StringUtils.hasText(enumHandlerRef)) { bean.addPropertyReference(Conventions.attributeNameToPropertyName(SETUP_ENUM_HANDLER_ATTR), enumHandlerRef); } String onMissingHandlers = element.getAttribute(SETUP_ON_MISSING_HANDLERS_ATTR); if (StringUtils.hasText(onMissingHandlers)) { bean.addPropertyValue(Conventions.attributeNameToPropertyName(SETUP_ON_MISSING_HANDLERS_ATTR), onMissingHandlers.toUpperCase()); } String propertyWritingMechanism = element.getAttribute(SETUP_PROPERTY_WRITING_MECHANISM_ATTR); if (StringUtils.hasText(propertyWritingMechanism)) { bean.addPropertyValue(Conventions.attributeNameToPropertyName(SETUP_PROPERTY_WRITING_MECHANISM_ATTR), propertyWritingMechanism.toUpperCase()); } String countCallback = element.getAttribute(SETUP_COUNT_CALLBACK_ATTR); String countCallbackRef = element.getAttribute(SETUP_COUNT_CALLBACK_REF_ATTR); if (StringUtils.hasText(countCallback)) { bean.addPropertyReference(Conventions.attributeNameToPropertyName(SETUP_COUNT_CALLBACK_ATTR + "Name"), countCallback); } else if (StringUtils.hasText(countCallbackRef)) { bean.addPropertyReference(Conventions.attributeNameToPropertyName(SETUP_COUNT_CALLBACK_ATTR), countCallbackRef); } List propertyTypeHandlersElements = DomUtils.getChildElementsByTagName(element, PROPERTY_TYPE_HANDLER_TAG); ManagedMap propertyTypeHandlersMap = new ManagedMap(propertyTypeHandlersElements.size()); for (int i = 0; i < propertyTypeHandlersElements.size(); i++) { Element propertyTypeHandlerElement = (Element) propertyTypeHandlersElements.get(i); String propertyType = propertyTypeHandlerElement.getAttribute(PROPERTY_TYPE_HANDLER_PROPERTY_TYPE_ATTR); String handlerClass = propertyTypeHandlerElement.getAttribute(PROPERTY_TYPE_HANDLER_HANDLER_CLASS_ATTR); propertyTypeHandlersMap.put(propertyType, handlerClass); } bean.addPropertyValue(Conventions.attributeNameToPropertyName(PROPERTY_TYPE_HANDLER_TAG) + "sClassNames", propertyTypeHandlersMap); List propertyTypeHandlersRefElements = DomUtils.getChildElementsByTagName(element, PROPERTY_TYPE_HANDLER_REF_TAG); ManagedSet propertyTypeHandlersRefSet = new ManagedSet(propertyTypeHandlersRefElements.size()); for (int i = 0; i < propertyTypeHandlersRefElements.size(); i++) { Element propertyTypeHandlersRefElement = (Element) propertyTypeHandlersRefElements.get(i); // String propertyType = propertyTypeHandlersRefElement.getAttribute(PROPERTY_TYPE_HANDLER_PROPERTY_TYPE_ATTR); String handlerRef = propertyTypeHandlersRefElement.getAttribute(PROPERTY_TYPE_HANDLER_HANDLER_REF_ATTR); RuntimeBeanReference runtimeBeanReference = new RuntimeBeanReference(handlerRef); propertyTypeHandlersRefSet.add(runtimeBeanReference); } bean.addPropertyValue(Conventions.attributeNameToPropertyName(PROPERTY_TYPE_HANDLER_TAG) + "s", propertyTypeHandlersRefSet); List specificPropertyHandlerElements = DomUtils.getChildElementsByTagName(element, SPECIFIC_PROPERTY_HANDLER_TAG); ManagedMap specificPropertyHandlersMap = new ManagedMap(specificPropertyHandlerElements.size()); for (int i = 0; i < specificPropertyHandlerElements.size(); i++) { Element specificPropertyElement = (Element) specificPropertyHandlerElements.get(i); String targetClass = specificPropertyElement.getAttribute(SPECIFIC_PROPERTY_HANDLER_TARGET_CLASS_ATTR); String targetProperty = specificPropertyElement.getAttribute(SPECIFIC_PROPERTY_HANDLER_TARGET_PROPERTY_ATTR); String handlerClass = specificPropertyElement.getAttribute(SPECIFIC_PROPERTY_HANDLER_HANDLER_CLASS_ATTR); specificPropertyHandlersMap.put(targetClass + "." + targetProperty, handlerClass); } bean.addPropertyValue(Conventions.attributeNameToPropertyName(SPECIFIC_PROPERTY_HANDLER_TAG) + "sClassNames", specificPropertyHandlersMap); List specificPropertyHandlerRefElements = DomUtils.getChildElementsByTagName(element, SPECIFIC_PROPERTY_HANDLER_REF_TAG); ManagedSet specificPropertyHandlersRefSet = new ManagedSet(specificPropertyHandlerRefElements.size()); for (int i = 0; i < specificPropertyHandlerRefElements.size(); i++) { Element specificPropertyRefElement = (Element) specificPropertyHandlerRefElements.get(i); // String targetClass = specificPropertyRefElement.getAttribute(SPECIFIC_PROPERTY_HANDLER_TARGET_CLASS_ATTR); // String targetProperty = specificPropertyRefElement.getAttribute(SPECIFIC_PROPERTY_HANDLER_TARGET_PROPERTY_ATTR); String handlerRef = specificPropertyRefElement.getAttribute(SPECIFIC_PROPERTY_HANDLER_HANDLER_REF_ATTR); RuntimeBeanReference runtimeBeanReference = new RuntimeBeanReference(handlerRef); specificPropertyHandlersRefSet.add(runtimeBeanReference); } bean.addPropertyValue(Conventions.attributeNameToPropertyName(SPECIFIC_PROPERTY_HANDLER_TAG) + "s", specificPropertyHandlersRefSet); } } }